package com.alibaba.cola.event.core;

import com.alibaba.cola.event.EventHandlerI;
import com.alibaba.cola.event.common.EventI;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 事件控制中枢
 * @author shawnzhan.zxy
 * @date 2017/11/20
 */
@SuppressWarnings("rawtypes")
@Component
public class EventHub {
    @Getter
    @Setter
    private ConcurrentHashMap<Class<? extends EventI>, CopyOnWriteArraySet<EventHandlerI>> eventRepository = new ConcurrentHashMap<>();
    
    @Getter
    private Map<Class, Class> responseRepository = new HashMap<>();
    
    public List<EventHandlerI> getEventHandler(Class eventClass) {
        List<EventHandlerI> eventHandlerIList = findHandler(eventClass);
        if (eventHandlerIList == null || eventHandlerIList.size() == 0) {
            throw new RuntimeException(eventClass + "is not registered in eventHub, please register first");
        }
        // 根据Order排序
        AnnotationAwareOrderComparator.sort(eventHandlerIList);
        // TODO 后续可扩展过滤
        return eventHandlerIList;
    }

    /**
     * 注册事件
     * @param eventClz
     * @param executor
     */
    public void register(Class<? extends EventI> eventClz, EventHandlerI executor){
        CopyOnWriteArraySet<EventHandlerI> currentEventHandlers = eventRepository.get(eventClz);
        if (CollectionUtils.isEmpty(currentEventHandlers)) {
            CopyOnWriteArraySet<EventHandlerI> newSet = new CopyOnWriteArraySet<>();
            currentEventHandlers = MoreObjects.firstNonNull(eventRepository.putIfAbsent(eventClz, newSet), newSet);
        }
        currentEventHandlers.add(executor);
    }

    private List<EventHandlerI> findHandler(Class<? extends EventI> eventClz){
        CopyOnWriteArraySet<EventHandlerI> eventHandlers = eventRepository.get(eventClz);
        List<EventHandlerI> eventHandlerList = Lists.newArrayList(eventHandlers);
        return eventHandlerList;
    }

}
